package com.lovebridge.ui;

import org.apache.log4j.Logger;
import com.jiehoo.ooqi.*;
import com.lovebridge.service.IService;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.ext.AfterCompose;
import org.zkoss.zkplus.databind.BindingListModelList;
import org.zkoss.zul.*;
import org.zkoss.zul.event.PagingEvent;

import java.util.*;

/**
 * BaseWindow.
 */
public class BaseWindow extends Window implements AfterCompose
{
    protected Logger logger = Logger.getLogger(this.getClass());
    private static Map<String, String> orderMap = new HashMap<String, String>();
    private static Map<String, String> orderSequence = new HashMap<String, String>();
    Set<String> listNames = new HashSet<String>();
    Map<String, QueryInfo> queryInfos = new HashMap<String, QueryInfo>();
    Map<String, Set<String>> sortablePropertyMap = new HashMap<String, Set<String>>();
    protected IService service;

    static
    {
        orderMap.put("ascending", "asc");
        orderMap.put("descending", "desc");
        orderSequence.put("natural", "ascending");
        orderSequence.put("ascending", "descending");
        orderSequence.put("descending", "ascending");
    }

    protected String getDefaultListName()
    {
        return "";
    }

    void addListName(String listName)
    {
        listNames.add(listName);
    }

    void addSortableProperty(String property)
    {
        addSortableProperty(getDefaultListName(), property);
    }

    void addSortableProperty(String listName, String property)
    {
        Set<String> sortableProperties = sortablePropertyMap.get(listName);
        if (sortableProperties == null)
        {
            sortableProperties = new HashSet<String>();
            sortablePropertyMap.put(listName, sortableProperties);
        }
        sortableProperties.add(property);
    }

    protected Listbox getListbox(String listboxName)
    {
        return (Listbox) getFellow(listboxName);
    }

    protected Paging getPaging(String pagingName)
    {
        return (Paging) getFellow(pagingName);
    }

    protected Tabbox getTabbox(String tabboxName)
    {
        return (Tabbox) getFellow(tabboxName);
    }

    protected String getHeaderName(String listName, String property)
    {
        return listName + "_" + property + "Header";
    }

    protected String getListboxName(String name)
    {
        return name + "Listbox";
    }

    protected String getTabboxName(String name)
    {
        return name + "Tabbox";
    }

    protected String getPagingName(String name)
    {
        return getListboxName(name) + "Paging";
    }

    public void afterCompose()
    {
        for (String listName : listNames)
        {
            initQueryInfo(listName);
            addPagingListener(listName);
            Set<String> sortableProperties = sortablePropertyMap.get(listName);
            for (String property : sortableProperties)
            {
                addSortListener(listName, property);
            }
        }
    }

    private void initQueryInfo(String listName)
    {
        String pagingName = getPagingName(listName);
        final Paging paging = getPaging(pagingName);
        QueryInfo queryInfo = queryInfos.get(listName);
        if (queryInfo == null)
        {
            queryInfo = new QueryInfo();
            From from=new From(listName,listName.substring(0,1).toLowerCase());
            queryInfo.addFrom(from);
            queryInfo.addSelect(new Field("*"));
            queryInfos.put(listName, queryInfo);
        }
        queryInfo.setPageSize(paging.getPageSize());
    }

    private void addPagingListener(final String listName)
    {
        String pagingName = getPagingName(listName);
        final Paging paging = getPaging(pagingName);
        paging.addEventListener(
            "onPaging", new EventListener()
        {
            public void onEvent(Event event)
            {
                PagingEvent pagingEvent = (PagingEvent) event;
                int pageNumber = pagingEvent.getActivePage();
                int firstRow = pageNumber * paging.getPageSize();
                queryInfos.get(listName).setFirstRow(firstRow);
                refreshList(listName);
            }
        });
    }

    private void addSortListener(final String listName, final String property)
    {
        final Listheader header = (Listheader) getFellow(getHeaderName(listName, property));
        header.addEventListener(
            "onSort", new EventListener()
        {
            public void onEvent(Event event)
            {
                String direction = header.getSortDirection();
                String nextDirection = orderSequence.get(direction);
                QueryInfo queryInfo = queryInfos.get(listName);
                queryInfo.getSorts().clear();
                queryInfo.addSort(property, orderMap.get(nextDirection).equals("asc"));
                refreshList(listName);
                event.stopPropagation();
                header.setSortDirection(nextDirection);
                resetOtherColumns(listName, property);
            }
        });
    }

    private void resetOtherColumns(String listName, String property)
    {
        Set<String> sortableProperties = sortablePropertyMap.get(listName);
        for (String p : sortableProperties)
        {
            if (!p.equals(property))
            {
                Listheader header = (Listheader) getFellow(getHeaderName(listName, p));
                header.setSortDirection("natural");
            }
        }
    }

    public void refreshList(String name)
    {
        try
        {
            getListbox(getListboxName(name)).setModel(new BindingListModelList(list(name), false));
        }
        catch (Throwable t)
        {
            handleException(t);
        }
    }

    protected void handleException(Throwable t)
    {
        logger.error(t);
        throw new RuntimeException(t.getMessage(), t);
    }

    public List list()
    {
        return list(getDefaultListName());
    }

    public List list(String name)
    {
        try
        {
            SearchResult queryResult = service.query(name);
            String pagingName = getPagingName(name);
            getPaging(pagingName).setTotalSize(queryResult.getTotalRows());
            return queryResult.getPageResult();
        }
        catch (Throwable t)
        {
            handleException(t);
        }
        return null;
    }

    public void onSearch()
    {
        try
        {
            Component searchForm = getFellow("searchForm");
            searchForm.setVisible(!searchForm.isVisible());
        }
        catch (Throwable t)
        {
            handleException(t);
        }
    }

    public void onFind()
    {
        try
        {
            String searchProperty = (String) ((Listbox) getFellow("searchProperty")).getSelectedItem().getValue();
            String searchContent = ((Textbox) getFellow("searchContent")).getValue();
            QueryInfo queryInfo = queryInfos.get(getDefaultListName());
            queryInfo.getConditions().clear();
            queryInfo.getConditions().add(new Condition(searchProperty, Operator.like, searchContent + "%"));
            refreshList(getDefaultListName());
        }
        catch (Throwable t)
        {
            handleException(t);
        }
    }

    public void onClear()
    {
        try
        {
            ((Textbox) getFellow("searchContent")).setValue("");
            QueryInfo queryInfo = queryInfos.get(getDefaultListName());
            queryInfo.getConditions().clear();
            //queryInfo.getSorts().clear();
            refreshList(getDefaultListName());
        }
        catch (Throwable t)
        {
            handleException(t);
        }
    }
}